﻿using System;
using System.Collections.Generic;
using System.Text;

namespace AIFSContentManagementSystem.DomainObjects
{
    public abstract class CriterionExpression
    {
        protected const string EQUAL_TO = "=";
        protected const string LESS_THAN = "<";
        protected const string GREATER_THAN = ">";
        protected const string LESS_THAN_EQUAL_TO = "<=";
        protected const string GREATER_THAN_EQUAL_TO = ">=";
        protected const string NULL_STRING = "NULL";

        string leftOperand;
        public string LeftOperand
        {
            get { return leftOperand; }
            set { leftOperand = value; }
        }

        string rightOperand;
        public string RightOperand
        {
            get { return rightOperand; }
            set { rightOperand = value; }
        }

        string oper;
        public string Oper
        {
            get { return oper; }
            set { oper = value; }
        }

        /// <summary>
        /// Implement this to do derieved class specific checking if necessary.
        /// </summary>
        protected virtual bool CanCompare(CriterionExpression other)
        {
            return true;
        }

        /// <summary>
        /// Implement this to provide the data type associated with it.
        /// </summary>
        public abstract string DataType { get;}

        /// <summary>
        /// Implement this to actually perform the matching
        /// </summary>
        protected abstract int CompareTo(CriterionExpression other);

        public bool Match(CriterionExpression other)
        {
            //Make sure the expressions are comparable
            if (other == null)
                return false;

            if (string.IsNullOrEmpty(other.Oper) || string.IsNullOrEmpty(this.Oper))
                return false;

            if (string.IsNullOrEmpty(other.LeftOperand) || string.IsNullOrEmpty(this.LeftOperand))
                return false;

            if (string.IsNullOrEmpty(other.RightOperand) || string.IsNullOrEmpty(this.RightOperand))
                return false;

            if (!this.LeftOperand.Equals(other.LeftOperand))
                return false;

            //Check any specific rules for each expression types
            if (!this.CanCompare(other))
                return false;

            int compareResult = CompareTo(other);

            /*IF    THIS.OPER   other.OPER (from rule db)  CMP-RESULT MUST BE
             *      (from user) (from db)
             *      =           =           0
             *      =           <           -1
             *      =           >           1
             *      =           <=          0,-1
             *      =           >=          0,1
            */

            switch (other.Oper)
            {
                case EQUAL_TO:
                    if (compareResult == 0)
                        return true;
                    break;
                case LESS_THAN:
                    if (compareResult == -1)
                        return true;
                    break;
                case GREATER_THAN:
                    if (compareResult == 1)
                        return true;
                    break;
                case LESS_THAN_EQUAL_TO:
                    if (compareResult <= 0)
                        return true;
                    break;
                case GREATER_THAN_EQUAL_TO:
                    if (compareResult >= 0)
                        return true;
                    break;
            }

            return false;
        }
    }
}
